#pragma once
#ifndef _LINAL_BCG_
#define _LINAL_BCG_

//================================================================================================================================
//================================================================================================================================
// Локальные
#include "math/math.h"
#include "linal/vector.h"
#include "linal/csrmatrix.h"
#include "linal/slaesolver.h"
#include "core_global.h"

//================================================================================================================================
//================================================================================================================================
namespace linal
{
    /// Класс реализует решение СЛАУ методом БСГ.
    /// \sa Метод конечных элементов для решения скалярных и векторных задач : учеб. пособие / Ю.Г. Соловейчик, М.Э. Рояк,
    /// М.Г. Персова - Новосибирск: Изд-во НГТУ, 2007. - 896 с.
    class CORE_EXPORT BCG : public SLAESolver
    {
    public:
        BCG() : SLAESolver() {}
        BCG(int max_num_of_iter, double sufficient_residual) : SLAESolver(max_num_of_iter, sufficient_residual) {}

        /// Решение СЛАУ с матрицей в разреженном строчном формате.
        /// \param matrix Матрица СЛАУ.
        /// \param f Правая часть СЛАУ.
        /// \param [in,out] x На входе - начальное приближение решения СЛАУ. На выходе - решение СЛАУ.
        /// \return Невязка решения.
        double solve(const CSRMatrix &matrix, const Vector &f, Vector &x);

        /// Решение СЛАУ с матрицей в разреженном строчном формате c использование LU факторизации.
        /// \param matrix Матрица СЛАУ.
        /// \param f Правая часть СЛАУ.
        /// \param [in,out] x На входе - начальное приближение решения СЛАУ. На выходе - решение СЛАУ.
        /// \return Невязка решения.
        double solveLU(const CSRMatrix &matrix, const Vector &f, Vector &x)
        {
            Q_UNUSED(f);
            Q_UNUSED(x);
            Q_UNUSED(matrix);
            return std::numeric_limits<double>::max();
        }

        /// Решение СЛАУ с матрицей в разреженном строчном формате c использование диагональной факторизации.
        /// \param matrix Матрица СЛАУ.
        /// \param f Правая часть СЛАУ.
        /// \param [in,out] x На входе - начальное приближение решения СЛАУ. На выходе - решение СЛАУ.
        /// \return Невязка решения.
        double solveDi(const CSRMatrix &matrix, const Vector &f, Vector &x)
        {
            Q_UNUSED(f);
            Q_UNUSED(x);
            Q_UNUSED(matrix);
            return std::numeric_limits<double>::max();
        }

        /// Выделение памяти для вспомогательных векторов итерационного метода.
        //
        /// Для оптимизации работы с памятью вспомогательные вектора хранятся и в промежутках между
        /// решениями СЛАУ, а их размер меняется только по необходимости.
        void adaptForSLAE(int dimension)
        {
            m_R.resize(dimension);
            m_P.resize(dimension);
            m_Z.resize(dimension);
            m_S.resize(dimension);
        }

    private:
        Vector m_R;     ///< Вектор невязки.
        Vector m_P;     ///< Вспомогательный вектор метода.
        Vector m_Z;     ///< Вспомогательный вектор метода.
        Vector m_S;     ///< Вспомогательный вектор метода.

        Vector m_Az;    ///< Произведение матрицы A на вектор m_Z.
        Vector m_ATs;   ///< Произведение матрицы A^T на вектор m_S.
    };
}

#endif // _LINAL_BCG_
